package com.lottemall.cart.interceptor;

import com.lottemall.auth.entity.UserInfo;
import com.lottemall.auth.utils.JwtUtils;
import com.lottemall.cart.config.JwtProperties;
import com.lottemall.common.utils.CookieUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 自定义用户的拦截器（选择在达到Controller之前还是之后拦截）
 * 主要用于识别用户是谁
 * 还需要注意的是想让这个拦截器生效需要有一个类实现WebMvcConfigurer
 */
@Slf4j
public class UserInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtProperties jwtProperties;

    //创建一个线程池，因为一个请求对应一个线程，所以可以把用的token存入线程池中（key是线程的名字，value是值对象）
    private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();

    public UserInterceptor(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    /**
     * 请求到达Controller之前进行拦截，因为用户添加商品到购物车我们需要解析token知道用户是谁
     *
     * @param request
     * @param response
     * @param handler
     * @return true是放行
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取cookie中的token
        String token = CookieUtils.getCookieValue(request, jwtProperties.getCookieName());
        //解析token
        try {
            UserInfo userInfo = JwtUtils.getUserInfo(jwtProperties.getPublicKey(), token);
//            //传递userInfo(这里拦截到了就需要传递到Controller层)
//            request.setAttribute("user",userInfo);  //这里不推荐req传递
            //所以这里存入线程池，这里只有这个set简单方法，因为内部使用的是当前线程当做key
            tl.set(userInfo);
            //放行
            return true;
        } catch (Exception e) {
            log.error("[购物车服务]解析用户身份失败.", e);
            return false;//拦截
        }
    }

    /**
     * 之后记得删除线程池中存的userInfo,否则越来越多
     * 这个方法是在视图渲染完成后再进行
     *
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //最后用完数据一定要清空
        tl.remove();
    }

    /**
     * 得到用户信息（从线程域中）
     * @return
     */
    public static UserInfo getUser(){
        return tl.get();
    }
}
